var KEY = { ESC: 27, SPACE: 32, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40 };
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var fps = 25;
var frame = 0;
var activePiece;
var interval;
var bricks = new Array(200);
var last = new Date().getTime();
var brickSize = 40;
var score = 0;
JPiece.prototype = TPiece.prototype = LPiece.prototype = ZPiece.prototype = SPiece.prototype = IPiece.prototype = OPiece.prototype = new Piece();
var pieces = [LPiece, ZPiece, SPiece, IPiece, OPiece, TPiece, JPiece];

function init() {
	console.log("init");
	for ( var i = 0; i < bricks.length; i++)
		bricks[i] = new Brick();
	document.addEventListener('keydown', keydown, false);
	drawGrid();
}

function keydown(ev) {
	switch (ev.keyCode) {
	case KEY.LEFT:
		if(isLeftMoveAvailable())
			activePiece.x--;
		break;
	case KEY.RIGHT:	
		if(isRightMoveAvailable())
			activePiece.x++;
		break;
	case KEY.UP:	
		if(isRotationAvailable())
			activePiece.rotate();
		break;
	case KEY.DOWN:	
		if(isDownMoveAvailable())
			activePiece.y++;
		break;
	case KEY.ESC:				
		break;
	}
}

function startGame() {	
	createPiece();
	interval = setInterval(gameLoop, 1000 / fps);
}

function gameLoop() {
	var now = new Date().getTime();	
	if(Math.min(1, (now - last) / 1000.0) >= 1) {	
		last = new Date().getTime();
		updatePieces();
	}
	frame++;
	document.getElementById("frameCounter").innerHTML = "Frame: " + frame;
	document.getElementById("score").innerHTML = "Score: " + score;
	drawPieces();
}

function drawGrid() {
	ctx.lineWidth = 0.2;
	ctx.beginPath();
	for ( var x = 0; x <= 400; x += 40) {
		ctx.moveTo(x, 0);
		ctx.lineTo(x, 800);
	}
	for ( var y = 40; y <= 800; y += 40) {
		ctx.moveTo(0, y);
		ctx.lineTo(400, y);
	}
	ctx.closePath();
	ctx.stroke();
}

function drawPieces() {
	ctx.clearRect(0, 0, canvas.width, canvas.height);
	ctx.fillStyle = activePiece.color;
	var matrX = activePiece.x * 40;
	var matrY = activePiece.y * 40;
	for (var i = 0; i < 16; i++) {
		if (activePiece.bricks[activePiece.position][i] === 1) {
			x = i - 4 * (Math.floor(i / 4));
			y = Math.floor(i / 4);
			ctx.fillRect(matrX + x * 40, matrY + y * 40, 40, 40);
		}
	}	
	for (var i = 0; i < bricks.length; i++) {
		if (bricks[i].filled === 1) {
			ctx.fillStyle = bricks[i].color;
			x = i - 10 * (Math.floor(i / 10));
			y = Math.floor(i / 10);
			ctx.fillRect(x * 40, y * 40, 40, 40);
		}
	}
	drawGrid();
}

function updatePieces() {
	console.log("check");
	if(isDownMoveAvailable())
		activePiece.y++;
	checkForFilledLines();	
}

function createPiece() {
	activePiece = getRandomPiece();		
}

function checkForFilledLines() {	
	for(var i = 19; i >= 0; i--) {
		var filledLine = true;
		for(var j = i*10 + 9; j >= i*10; j--) {			
			if(bricks[j].filled === 0) {
				filledLine = false;
				break; //Check for outer cycle break
			}
		}
		if(filledLine) {
			score++;
			for(var j = i*10 + 9; j >= i*10; j--) {
				bricks[j].filled = 0;
			}
			for(var k = i*10 + 9; k >= 0; k--) {
				if(bricks[k].filled === 1) {					
					bricks[k].filled = 0; 
					bricks[k+10].filled = 1;
					bricks[k+10].color = bricks[k].color;
				}
			}
		}
	}
}

function isRotationAvailable() {	
	for (var i = 0; i < 16; i++) {		
		if (activePiece.bricks[activePiece.getNextPos()][i] === 1) {	
			if(activePiece.x > 6) {
				if(i % 4 > (9 - activePiece.x))
					return false;
			}
			if(activePiece.x < 0) {
				if(i % 4 < Math.abs(activePiece.x))
					return false;
			}
			if(activePiece.y > 16) {
				if(Math.floor(i / 4) >= 4 - (activePiece.y - 16))
					return false;
			}					
			if(bricks[getIndex(i)].filled === 1) 
				return false;
		}
	}
	return true;
}

function isDownMoveAvailable() {
	for (var i = 0; i < 16; i++) {
		if (activePiece.bricks[activePiece.position][i] === 1) {						
			var index = getIndex(i) + 10;
			if (index > 199 || bricks[index].filled === 1) {
				landActivePiece();
				createPiece();
				return false;
			}
		}
	}
	return true;
}

function isLeftMoveAvailable() {
	for (var i = 0; i < 16; i++) {
		if (activePiece.bricks[activePiece.position][i] === 1) {
			var index = getIndex(i) - 1;
			if(((index+1) % 10 === 0) || bricks[index].filled === 1) 
				return false;
		}
	}
	return true;
}

function isRightMoveAvailable() {
	for (var i = 0; i < 16; i++) {
		if (activePiece.bricks[activePiece.position][i] === 1) {
			var index = getIndex(i) + 1;	
			if((index % 10 === 0) || bricks[index].filled === 1) 
				return false;
		}
	}
	return true;
}

function landActivePiece() {
	for (var i = 0; i < 16; i++) {
		if (activePiece.bricks[activePiece.position][i] === 1) {	
			var index = getIndex(i);
			bricks[index].color = activePiece.color;
			bricks[index].filled = 1;
		}
	}
}

function getIndex(i) {
	return (activePiece.y + 1)*10 - (10-activePiece.x) + i + 10*(Math.floor(i/4)) - 4*(Math.floor(i/4));
}

function getRandomPiece() {
	return new pieces[Math.floor(Math.random() * (7))];
}

function Brick() {
	
	this.filled = 0;
	this.color = "";
	
}

function Piece() {
	
	this.position = 0;
	this.x = 3;
	this.y = -1;
	
	this.rotate = function() {
		if(this.position < this.bricks.length-1)
			this.position++;
		else 
			this.position = 0;		
	}
	
	this.getNextPos = function() {
		if(this.position < this.bricks.length-1)
			return this.position+1;
		else return 0;
	}
	
}

function JPiece() {

	this.bricks = [[ 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
	               [ 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 ]];
	this.color = "red";
	
}

function LPiece() {

	this.bricks = [[ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 ], 
	               [ 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]];
	this.color = "green";
	
}

function TPiece() {

	this.bricks = [[ 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 ], 
	               [ 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 ]];
	this.color = "#EBCF1E";
	
}

function ZPiece() {

	this.bricks = [[ 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 ]];
	this.color = "blue";
	
}

function SPiece() {

	this.bricks = [[ 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 ]];
	this.color = "#11ECF0";
	
}

function IPiece() {

	this.bricks = [[ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0 ]];
	this.color = "#1118F0";
	
}

function OPiece() {

	this.bricks = [[ 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 ]];
	this.color = "#9E11F0";
	
}